﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using Point2d.Geometry;

namespace Point2d.Graphics
{
    public class GraphicsManager
    {
        public ViewControl _viewControl = null;
        public EntityFactory _factory = null;
        public DataSupplier _dataSupplier = null;

        public static Pen _graphicsPen = Pens.Black;
        public static Brush _graphicsBrush = Brushes.Black;

        public Size _viewSize = Size.Empty;

        SortedDictionary<int, List<Entity>> _entities = new SortedDictionary<int, List<Entity>>();
        PointF _origin2 = PointF.Empty;
        float _scale = 1.0f;

        public GraphicsManager()
        {
            _viewControl = new ViewControl(this);
            _factory = new EntityFactory(this);
            _dataSupplier = new DataSupplier();
        }

        public void Draw(System.Drawing.Graphics graphics)
        {
            foreach (var level in _entities)
            {
                foreach (var entity in level.Value)
                {
                    entity.Draw(graphics);
                }
            }
        }

        // transform from world to view
        // let
        // pt is the point in world
        // scale is the length scale from world to view
        // origin2 is the origin in view
        // pt2 is the point in view
        // then
        // pt2.x = pt.x * scale + origin2.x
        // pt2.y = pt.y * scale + origin2.y
        public void GetPointFromWorld2View(Point2 pointOfWorld, ref float x, ref float y)
        {
            x = pointOfWorld._x * _scale + _origin2.X;
            y = pointOfWorld._y * _scale + _origin2.Y;
        }

        public void Append(Entity entity, int level = 0)
        {
            if (_entities.ContainsKey(level) == false)
            {
                _entities.Add(level, new List<Entity>());
            }

            _entities[level].Add(entity);
        }

        public void Move(Vector2 size)
        {
            _origin2.X += size._width;
            _origin2.Y += size._height;
        }

        void Move(float offsetX, float offsetY)
        {
            _origin2.X += offsetX;
            _origin2.Y += offsetY;
        }

        public void Scale(float delta, int viewWidth, int viewHeight)
        {
            float scale_Before = _scale;
            float scale_After = _scale * delta;

            float centerOfView_BeforeX = viewWidth / 2;
            float centerOfView_BeforeY = viewHeight / 2;

            float centerOfWorld_BeforeX = (centerOfView_BeforeX - _origin2.X) / scale_Before;
            float centerOfWorld_BeforeY = (centerOfView_BeforeY - _origin2.Y) / scale_Before;
            float centerOfView_AfterX = centerOfWorld_BeforeX * scale_After + _origin2.X;
            float centerOfView_AfterY = centerOfWorld_BeforeY * scale_After + _origin2.Y;

            // move delta offset from before to after for center
            Move(-(centerOfView_AfterX - centerOfView_BeforeX), -(centerOfView_AfterY - centerOfView_BeforeY));

            _scale = scale_After;
        }
    }
}
